﻿using lclBridgeTool;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

namespace AutoCadDraw
{
    public static class Tool
    {
        /// <summary>
        /// 将data数据实例化到指定类中
        /// </summary>
        /// <param name="type">类型名</param>
        /// <param name="data">数据</param>
        /// <param name="dllPathName">指定类所在dll全名称，不给则默认在当前dll中找</param>
        /// <returns></returns>
        public static object TypeToExample(string type, string data, string dllPathName = null)
        {

            Type type1 = Type.GetType(type);
            if (dllPathName != null)
            {
                System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(dllPathName);
                type1 = assembly.GetType(type);
            }
/*            string ss = "AAA";
            string v1 = JsonConvert.SerializeObject(ss);
            Type type2 = Type.GetType("System.String");
            JsonConvert.DeserializeObject(v1,type2);*/
            object v = JsonConvert.DeserializeObject(data, type1);
            return v;
        }

        /// <summary>
        /// 将data数据实例化到指定类中
        /// </summary>
        /// <param name="type">类型名</param>
        /// <param name="data">数据</param>
        /// <param name="dllPathName">指定类所在dll全名称，不给则默认在当前dll中找</param>
        /// <returns></returns>
        public static object TypeToExample(string type, string data, System.Reflection.Assembly assembly)
        {

            Type type1 = Type.GetType(type);
            if (assembly != null)
            {
                type1 = assembly.GetType(type);
            }
            /*            string ss = "AAA";
                        string v1 = JsonConvert.SerializeObject(ss);
                        Type type2 = Type.GetType("System.String");
                        JsonConvert.DeserializeObject(v1,type2);*/
            object v = JsonConvert.DeserializeObject(data, type1);
            return v;
        }

        public static object TypeToExample(string type, string data, List<string> dllPathName)
        {
            Type type1 = Type.GetType(type);
            List<System.Reflection.Assembly> assemblys = new List<System.Reflection.Assembly>();
            System.Reflection.Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
            List<string> dllPathNames = new List<string>();//文件名的集合不包含路径带后缀
            for (int i = 0; i < dllPathName.Count; i++)
            {
                string v1 = System.IO.Path.GetFileName(dllPathName[i]);
                dllPathNames.Add(v1);
            }
            for (int i = 0; i < assemblies.Length; i++)
            {
                if (assemblies[i] != null && assemblies[i].ManifestModule != null && assemblies[i].ManifestModule.Name != null && dllPathNames.Contains(assemblies[i].ManifestModule.Name))
                {
                    assemblys.Add(assemblies[i]);
                }
            }
            if (type1 == null)
            {
                type1 = TypeToExampleType(type, data, assemblys);
            }
            if (type1 == null)
            {
                foreach (string strPath in dllPathName)
                {
                    System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(strPath);
                    type1 = assembly.GetType(type);
                    if (type1 != null)
                    {
                        break;
                    }
                }
            }
            object v = JsonConvert.DeserializeObject(data, type1);

            return v;
        }
        public static Type TypeToExampleType(string type, string data, List<System.Reflection.Assembly> assemblys)
        {
            Type type1 = Type.GetType(type);
            if (type1 == null)
            {
                foreach (System.Reflection.Assembly assembly in assemblys)
                {
                    type1 = assembly.GetType(type);
                    if (type1 != null)
                    {
                        break;
                    }
                }
            }

            return type1;
        }
        /// <summary>
        /// 类名
        /// </summary>
        /// <param name="Type"></param>
        public static void UnitConversion(string Type)
        {

        }
        /// <summary>
        /// 获取指定名称空间下的所有类名
        /// </summary>
        /// <param name="dllPathName">dll全名称</param>
        /// <param name="nameSpace">命名空间</param>
        /// <returns>返回指定命名空间下的所有类名</returns>
        public static List<string> GetClassNmaes(string dllPathName, string nameSpace)
        {
            List<string> classNames = new List<string>();
            System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(dllPathName);
            foreach (Type type in assembly.GetTypes())
            {
                if (type.Namespace == nameSpace)
                {
                    classNames.Add(type.Name);
                }
            }
            return classNames;
        }
        /// <summary>
        /// 获取指定名称空间下的所有类名
        /// </summary>
        /// <param name="assembly">程序集</param>
        /// <param name="nameSpace">命名空间</param>
        /// <returns>返回指定命名空间下的所有类名</returns>
        public static List<string> GetClassNmaes(Assembly assembly, string nameSpace)
        {
            List<string> classNames = new List<string>();
            foreach (Type type in assembly.GetTypes())
            {
                if (type.Namespace == nameSpace)
                {
                    classNames.Add(type.Name);
                }
            }
            return classNames;
        }
        /// <summary>
        /// 在指定命名空间下将json反序列化成实例
        /// </summary>
        /// <param name="dllPathNames">dll全名称集合</param>
        /// <param name="nameSpace">命名空间</param>
        /// <param name="json">json</param>
        /// <returns></returns>
        public static object JsonToExample(List<string> dllPathNames, string nameSpace, string json)
        {
            //拿到当前json的所有属性
            List<string> propertes = new List<string>();
            JObject keyValuePairs = (JObject)JsonConvert.DeserializeObject(json);
            foreach (var item in keyValuePairs)
            {
                propertes.Add(item.Key);
            }
            //拿到该命名空间下所有类名
            List<string> list = new List<string>();
            dllPathNames.ForEach(x => list.AddRange(GetClassNmaes(x, nameSpace)));
            List<string> classNames = new List<string>();
            for (int i = 0; i < list.Count; i++)
            {
                string classPath = nameSpace + "." + list[i];
                classNames.Add(classPath);
            }
            (string, string) className_dll = GetClassNmae(dllPathNames, classNames, json);
            object v = TypeToExample(className_dll.Item1, json, className_dll.Item2);
            return v;
        }
        /// <summary>
        /// 在指定命名空间下将json反序列化成实例
        /// </summary>
        /// <param name="assemblys">所有程序集</param>
        /// <param name="nameSpace">命名空间</param>
        /// <param name="json">json</param>
        /// <returns></returns>
        public static object JsonToExample(List<Assembly> assemblys, string nameSpace, string json)
        {
            //拿到当前json的所有属性
            List<string> propertes = new List<string>();
            JObject keyValuePairs = (JObject)JsonConvert.DeserializeObject(json);
            foreach (var item in keyValuePairs)
            {
                propertes.Add(item.Key);
            }
            //拿到该命名空间下所有类名
            List<string> list = new List<string>();
            assemblys.ForEach(x => list.AddRange(GetClassNmaes(x, nameSpace)));
            List<string> classNames = new List<string>();
            for (int i = 0; i < list.Count; i++)
            {
                string classPath = nameSpace + "." + list[i];
                classNames.Add(classPath);
            }
            (string, Assembly) className_assembly = GetClassNmae(assemblys, classNames, json);
            object v = TypeToExample(className_assembly.Item1, json, className_assembly.Item2);
            return v;
        }
        /// <summary>
        /// 在指定类集合中找到符合json结构的类（只完成第一层属性名比对，如果属性数量与名称一致将匹配成功）
        /// </summary>
        /// <param name="dllPathNames">dll全名称集合</param>
        /// <param name="classNames">全路径类名集合</param>
        /// <param name="json">json</param>
        /// <returns>(返回全路径类名,所在dll)-没找到将报错</returns>
        public static (string className, string dllPathName) GetClassNmae(List<string> dllPathNames, List<string> classNames, string json)
        {
            //拿到当前json的所有属性
            List<string> propertes = new List<string>();
            JObject keyValuePairs = (JObject)JsonConvert.DeserializeObject(json);
            foreach (var item in keyValuePairs)
            {
                propertes.Add(item.Key);
            }

            //符合条件的类,类所在dll
            List<(string, string)> classNameReturns = new List<(string,string)>();
            for (int ii = 0; ii < dllPathNames.Count; ii++)
            {
                System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(dllPathNames[ii]);
                for (int i = 0; i < classNames.Count; i++)
                {
                    Type type = assembly.GetType(classNames[i]);
                    if (type == null)
                    {
                        continue;
                    }
                    //拿到当前类的所有属性+字段
                    List<string> list1 = type.GetProperties().Select(x => x.Name).ToList();
                    List<string> list = type.GetFields().Select(x => x.Name).ToList();
                    list1.AddRange(list);
                    if (list1.Count == propertes.Count)
                    {
                        int js = 0;
                        for (int j = 0; j < propertes.Count; j++)
                        {
                            if (list1.Contains(propertes[j]))
                            {
                                js++;
                            }
                        }
                        if (list1.Count == js)
                        {
                            classNameReturns.Add((classNames[i], dllPathNames[ii]));
                        }
                    }
                }
            }
            if (classNameReturns.Count != 0)
            {
                return classNameReturns[0];
            }
            else
            {
                //return null;
                throw new Exception("在GetGetClassNmae(List<string> classNames, string json)发现错误:没有在指定类中找到符合json结构的类。");
            }
        }
        /// <summary>
        /// 在指定类集合中找到符合json结构的类（只完成第一层属性名比对，如果属性数量与名称一致将匹配成功）
        /// </summary>
        /// <param name="assemblys">所有程序集</param>
        /// <param name="classNames">全路径类名集合</param>
        /// <param name="json">json</param>
        /// <returns>(返回全路径类名,所在dll)-没找到将报错</returns>
        public static (string className, Assembly assembly) GetClassNmae(List<Assembly> assemblys, List<string> classNames, string json)
        {
            //拿到当前json的所有属性
            List<string> propertes = new List<string>();
            JObject keyValuePairs = (JObject)JsonConvert.DeserializeObject(json);
            foreach (var item in keyValuePairs)
            {
                propertes.Add(item.Key);
            }

            //符合条件的类,类所在dll
            List<(string, Assembly)> classNameReturns = new List<(string, Assembly)>();
            for (int ii = 0; ii < assemblys.Count; ii++)
            {
                System.Reflection.Assembly assembly = assemblys[ii];
                for (int i = 0; i < classNames.Count; i++)
                {
                    Type type = assembly.GetType(classNames[i]);
                    if (type == null)
                    {
                        continue;
                    }
                    //拿到当前类的所有属性+字段
                    List<string> list1 = type.GetProperties().Select(x => x.Name).ToList();
                    List<string> list = type.GetFields().Select(x => x.Name).ToList();
                    list1.AddRange(list);
                    if (list1.Count == propertes.Count)
                    {
                        int js = 0;
                        for (int j = 0; j < propertes.Count; j++)
                        {
                            if (list1.Contains(propertes[j]))
                            {
                                js++;
                            }
                        }
                        if (list1.Count == js)
                        {
                            classNameReturns.Add((classNames[i], assemblys[ii]));
                        }
                    }
                }
            }
            if (classNameReturns.Count != 0)
            {
                return classNameReturns[0];
            }
            else
            {
                //return null;
                throw new Exception("在GetGetClassNmae(List<string> classNames, string json)发现错误:没有在指定类中找到符合json结构的类。");
            }
        }
        /// <summary>
        /// 在指定程序集中找到符合json结构的类（只完成第一层属性名比对，如果属性数量与名称一致将匹配成功）
        /// </summary>
        /// <param name="assemblys">指定装配集</param>
        /// <param name="json"></param>
        /// <returns>(返回全路径类名,所在Assembly)-没找到将报错</returns>
        public static (string className, Assembly Assembly) GetClassName(List<Assembly> assemblys, string json)
        {
            try
            {
                List<string> propertes = new List<string>();
                JObject keyValuePairs = (JObject)JsonConvert.DeserializeObject(json);
                foreach (var item in keyValuePairs)
                {
                    propertes.Add(item.Key);
                }
                List<(string, Assembly)> classNameReturns = new List<(string, Assembly)>();
                //第一步，拿到json中所有的属性
                for (int i = 0; i < assemblys.Count; i++)
                {
                    List<Type> types = assemblys[i].GetTypes().ToList();
                    for (int j = 0; j < types.Count; j++)
                    {
                        Type type = types[j];
                        List<string> list1 = type.GetProperties(BindingFlags.Instance |BindingFlags.Public).Select(x => x.Name).ToList();
                        List<string> list = type.GetFields(BindingFlags.Instance | BindingFlags.Public).Select(x => x.Name).ToList();
                        list1.AddRange(list);
                        //第二步，拿到type中的所有属性和字段
                        if (list1.Count == propertes.Count)//第三步,判断type中的所有属性和字段的个数与json中所有的属性的个数是否一致
                        {//一致
                         //判断type中的所有属性和字段名称与json中所有的属性名称是否完全一致
                         // if (true)
                         //{//完全一致
                         //返回当前type的全路径类名以及Assembly
                         //}

                            //Vector3d
                            int js = 0;
                            for (int jj = 0; jj < propertes.Count; jj++)
                            {
                                if (list1.Contains(propertes[jj]))
                                {
                                    js++;
                                }
                            }
                            if (list1.Count == js)
                            {
                                classNameReturns.Add((types[j].FullName, assemblys[i]));
                            }

                        }
                    }

                }
                if (classNameReturns.Count != 0)
                {
                    return classNameReturns[0];
                }
                else
                {
                    return (null, null);
                    //throw new Exception("在GetGetClassNmae(List<string> classNames, string json)发现错误:没有在指定类中找到符合json结构的类。");
                }
            }
            catch (Exception ex)
            {
                return (null,null);
            }
            //return (null,null);
        }

        public static List<Entity> TransByMatrix(Matrix3d myMatrix, List<Entity> list)
        {
            List<Entity> entities = new List<Entity>();
            list.ForEach(u => { u.TransformBy(myMatrix); entities.Add(u); });
            return entities;
        }
        /// <summary>
        /// 某一图形按单位缩放
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="scale"></param>
        /// <returns></returns>
        public static Entity EntityUnitConvert(Entity entity,double scale)
        {
            entity.Scale(scale,new Point3d(0, 0, 0));
            return entity;
        }
    }
}
